package cn.kgc.vue.shiro;

import cn.kgc.vue.entity.RolePers;
import cn.kgc.vue.entity.UserRole;
import cn.kgc.vue.mapper.PermissionMapper;
import cn.kgc.vue.mapper.RoleMapper;
import cn.kgc.vue.mapper.RolePersMapper;
import cn.kgc.vue.mapper.UserRoleMapper;
import cn.kgc.vue.utils.JWTUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Author: 课工场
 * @Version: v1.0  2023/8/9
 * @Description:
 */
public class CustomerRealm extends AuthorizingRealm {
    
    @Autowired
    private UserRoleMapper userRoleMapper;

    @Autowired
    private RoleMapper roleMapper;

    @Autowired
    private RolePersMapper rolePersMapper;

    @Autowired
    private PermissionMapper permissionMapper;
    
    // 判定是否支持 JWTToken    UnsupportedTokenException
    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof JWTToken;
    }

    // 授权方法
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        System.out.println("==============授权doGetAuthorizationInfo====================");
        Object primaryPrincipal = principals.getPrimaryPrincipal();
        System.out.println("primaryPrincipal = " + primaryPrincipal);
        // 根据用的id 查询用户的角色信息    admin
        LambdaQueryWrapper<UserRole> lambda = new QueryWrapper<UserRole>().lambda();
        lambda.eq(UserRole::getUserId,primaryPrincipal);
        List<Integer> rids = userRoleMapper.selectList(lambda).stream().map(ur -> ur.getRoleId()).collect(Collectors.toList());

        //角色字符串
        List<String> roles = roleMapper.selectBatchIds(rids).stream().map(r -> r.getRoleEn()).collect(Collectors.toList());

        //根据角色id  role_permission   pids
        LambdaQueryWrapper<RolePers> lambda1 = new QueryWrapper<RolePers>().lambda();
        lambda1.in(RolePers::getRoleId,rids);
        List<Integer> pids = rolePersMapper.selectList(lambda1).stream().map(rp -> rp.getPerId()).collect(Collectors.toList());

        // pids  查询权限字符串
        List<String> permissions = permissionMapper.selectBatchIds(pids).stream().map(p -> p.getPermission()).collect(Collectors.toList());

        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        // 添加角色权限
        simpleAuthorizationInfo.addRoles(roles);
        //添加权限字符串
        simpleAuthorizationInfo.addStringPermissions(permissions);

        return simpleAuthorizationInfo;
    }
    // 认证方法  默认情况下  认证通过 会将用户信息 存储在session中  访问的是受限资源 被shiro提供的表单认证过滤器拦截
    // 前后端分离   验证token的真伪
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        //System.out.println("==============认证doGetAuthenticationInfo====================");
        // 判定token
        JWTToken jwtToken = (JWTToken) token;
        String tk = jwtToken.getToken();
        System.out.println("tk = " + tk);

        JWTUtil.verifyToken(tk);

        // 获取用户id
        Map<String, Object> claim = JWTUtil.getClaim(tk);
        Object userId = claim.get("userId");
        System.out.println("userId = " + userId);

        SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(userId,tk,this.getName());
        return simpleAuthenticationInfo;

    }
}
